#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

class TCPServer
{
public:
    TCPServer(int port)
        : m_port(port), m_ip("0")
    {
    }
    int CreateSocket()
    {
        m_sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (m_sockfd < 0)
        {
            std::cout << "tcp socket create fail" << std::endl;
            exit(1);
        }
        std::cout << "tcp socket create success" << std::endl;
        return m_sockfd;
    }
    void BindSocket()
    {
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(m_port);
        // inet_pton(AF_INET, m_ip.c_str(), &addr.sin_addr);
        addr.sin_addr.s_addr = inet_addr(m_ip.c_str());

        socklen_t len = sizeof(addr);
        int n = bind(m_sockfd, (struct sockaddr *)&addr, len);
        if (n < 0)
        {
            std::cout << "tcp socket bind fail" << std::endl;
            exit(1);
        }
        std::cout << "tcp socket bind success" << std::endl;
    }
    void Listener()
    {
        // listen
        int listen_n = listen(m_sockfd, 8);
        if (listen_n < 0)
        {
            std::cout << "tcp socket listen fail" << std::endl;
            exit(1);
        }
        std::cout << "tcp socket listen success" << std::endl;
    }
    int Accepter()
    {
        struct sockaddr_in addr;
        socklen_t len;
        int listenfd = accept(m_sockfd, (struct sockaddr *)&addr, &len);
        if (listenfd < 0)
        {
            std::cout << "tcp socket accept fail" << std::endl;
        }
        std::cout << "tcp socket accept success" << std::endl;
        return listenfd;
    }
    void Init()
    {
        CreateSocket();
        BindSocket();
        Listener();
    }
    void loop()
    {
        while (true)
        {
            int listenfd = Accepter();
            Service(listenfd);
        }
    }
    void Service(int listenfd)
    {
        while (true)
        {
            char read_message[1024] = {0};
            int read_n = recv(listenfd, read_message, sizeof(read_message) - 1, 0);
            if (read_n < 0)
            {
                std::cout << "read fail" << std::endl;
                exit(1);
            }
            else if (read_n == 0)
            {
                std::cout << "read end" << std::endl;
                exit(1);
            }
            std::cout << "read success: " << read_message << std::endl;

            // write --- return read_message
            std::string echo_message = "[echo message] #";
            echo_message += read_message;
            int write_n = send(listenfd, read_message, read_n, 0);
            if (write_n < 0)
            {
                std::cout << "write fail" << std::endl;
                exit(1);
            }
            std::cout << "write success!" << std::endl;
        }
    }
    ~TCPServer()
    {
    }

private:
    int m_sockfd;
    int m_port;
    std::string m_ip;
};